package com.fanvil.videoconference;

import android.view.Surface;

import com.fanvil.videoconference.FvlVideoConsumer;
import com.fanvil.videoconference.FvlSurfaceHolder;
import com.fanvil.videoconference.FvlLogger;

public class VideoManager {
    private static FvlLogger sLogger = FvlLogger.getLogger(VideoManager.class.getSimpleName(), FvlLogger.DEBUG);

    private FvlSurfaceHolder mLocalDisplay = null;
    private FvlVideoConsumer mLocalRenderer = null;
    private FvlSurfaceHolder mRemoteDisplay = null;
    private FvlVideoConsumer mRemoteRenderer = null;

    private AvcEncoder mRemote1Encoder;
    private AvcEncoder mRemote2Encoder;

    private h264Decoder mLocalH264Decoder = null;
    private h264Decoder mRemoteH264Decoder = null;
    private h264Decoder mRemote2H264Decoder = null;

    private static VideoManager sInstance;

    public static VideoManager getInstance() {
        if (sInstance == null) {
            sInstance = new VideoManager();
        }
        return sInstance;
    }

    private VideoManager() {
        FvlVideoConsumer remoteRenderer = FvlVideoConsumer.getRemote();
        remoteRenderer.start();
    }
/*
    public int setLocalDisplay(FvlSurfaceHolder local) {
        sLogger.d("setLocalDisplay: local=" + local);

        FvlVideoWindow localWindow = FvlVideoWindow.getLocal();
        FvlVideoConsumer localRenderer = FvlVideoConsumer.getLocal();
        FvlVideoConsumer remoteRenderer = FvlVideoConsumer.getRemote();

        if (localWindow == null || localRenderer == null || remoteRenderer == null) {
            sLogger.e("setLocalDisplay: video window or video renderer is null.");
            return -1;
        }

        if (mLocalDisplay != null && local != null && !local.equals(mLocalDisplay) && local.getState() == FvlSurfaceHolder.State.DESTORYED) {
            sLogger.d("setLocalDisplay: NOT Destory Same Local Display! local=" + local + " current=" + mLocalDisplay);
            return -1;
        }

        if (mLocalDisplay != null && local != null && local.equals(mLocalDisplay) && local.getState() != FvlSurfaceHolder.State.DESTORYED) {
            sLogger.d("setLocalDisplay: Same Local Display  local=" + local + " current=" + mLocalDisplay);
            if (mLocalRenderer != null) {
                sLogger.d("setLocalDisplay: Same Local Renderer (" + mLocalRenderer + ")");
                local.setRenderer(mLocalRenderer);
            }
        }
        mLocalDisplay = local;
        if (mLocalDisplay != null) {
            if (mLocalDisplay.isActive()) {
                sLogger.d("setLocalDisplay: Local Display (" + mLocalDisplay + ") is Active.");
                    sLogger.d("setLocalDisplay: Local Renderer (" + mLocalRenderer + ") is created.");
                    if (localRenderer != null) {
                        sLogger.d("setLocalDisplay: Local Renderer (" + mLocalRenderer + ") start");
                        
                        localRenderer.start();
                        //mLocalEncoder = new AvcEncoder(1920,1080, 25, "/sdcard/test1.h264");
                        localWindow.setRenderer(localRenderer);
                        localRenderer.setVideoSize(0, 1920, 1080);
                        localRenderer.setViewRole(0, 0);
                        localRenderer.addOutputSurface(0, mLocalDisplay.getSurface());

                        if (mLocalH264Decoder == null) {
                            mLocalH264Decoder = new h264Decoder(localRenderer.getSurface(0), "/sdcard/Download/h264_1920_1080.h264");
                            //mLocalH264Decoder.start();
                        }

                        //mLocalRenderer.addMediaCodecSurface(mLocalEncoder.createInputSurface());
                        //mLocalEncoder.StartEncoderThread();
                    }
            } else {
                sLogger.d("setLocalDisplay: Local Display (" + mLocalDisplay + ") is InActive.");
                mLocalDisplay.setRenderer(null);
                //nativeSetVideoDisplay(chan, 0, mLocalDisplay);
                if (mLocalH264Decoder != null) {
                    mLocalH264Decoder.interrupt();
                }
                //if (mLocalEncoder != null) {
                //    mLocalEncoder.StopThread();
                //}
                if (localRenderer != null) {
                    sLogger.d("setLocalDisplay: Local Renderer (" + mLocalRenderer + ") stop");

                    localRenderer.removeOutputSurface(0);

                } else {
                    sLogger.d("setLocalDisplay: Local Renderer (" + mLocalRenderer + ") is null.");
                }
                return 0;
            }
        } else {
            sLogger.d("setLocalDisplay: Local Display (" + mLocalDisplay + ") is null.");
        }

        //return nativeSetVideoDisplay(chan, 0, mLocalDisplay);
        return 0;
    }
*/
    public int setRemoteDisplay(int index, FvlSurfaceHolder remoteHolder) {
        sLogger.d("setRemoteDisplay:  remote=" + remoteHolder);

        //FvlVideoWindow remoteWindow = FvlVideoWindow.getRemote();
        //FvlVideoConsumer localRenderer = FvlVideoConsumer.getLocal();
        FvlVideoConsumer remoteRenderer = FvlVideoConsumer.getRemote();

        //if (remoteWindow == null || remoteRenderer == null) {
        //    sLogger.e("setRemoteDisplay: video window or video renderer is null.");
        //    return -1;
        //}

        if (mRemoteDisplay != null && remoteHolder != null && !remoteHolder.equals(mRemoteDisplay) && remoteHolder.getState() == FvlSurfaceHolder.State.DESTORYED) {
            sLogger.d("setRemoteDisplay: NOT Destory Same Remote Display! remote=" + remoteHolder + " current=" + mRemoteDisplay);
            return -1;
        }

        if (mRemoteDisplay != null && remoteHolder != null && remoteHolder.equals(mRemoteDisplay) && remoteHolder.getState() != FvlSurfaceHolder.State.DESTORYED) {
            sLogger.d("setRemoteDisplay: Same Remote Display remote=" + remoteHolder + " current=" + mRemoteDisplay);
            if (mRemoteRenderer != null) {
                sLogger.d("setRemoteDisplay: Same Remote Renderer (" + mRemoteRenderer + ")");
                remoteHolder.setRenderer(mRemoteRenderer);
            }
        }

        mRemoteDisplay = remoteHolder;
        if (mRemoteDisplay != null) {
            if (mRemoteDisplay.isActive()) {
                sLogger.d("setRemoteDisplay: Remote Display (" + mRemoteDisplay + ") is Active.");
                        remoteRenderer.start();
                        sLogger.d("setRemoteDisplay: Remote Renderer (" + mRemoteRenderer + ") start");
                        mRemoteDisplay.setRenderer(mRemoteRenderer);
                        remoteRenderer.setVideoSize(index, 1920, 1080);
                        //remoteRenderer.setVideoSize(index, 1280, 720);
                        remoteRenderer.setViewRole(index, 1);
                        //if (index == 2) {
                            //测试用ui surface代替encoder surface，显示是否正常
                        //    remoteRenderer.addOutputSurface(FvlVideoConsumer.ID_SHARE1, mRemoteDisplay.getSurface());
                        //} else {
                            remoteRenderer.addOutputSurface(index, mRemoteDisplay.getSurface());
                        //}

                        if (mRemote1Encoder == null) {
                            mRemote1Encoder = new AvcEncoder(1920, 1080, 25, "/sdcard/test1.h264");
                            //mRemote1Encoder = new AvcEncoder(1280, 720, 25, "/sdcard/test1.h264");
                            Surface inputSurface = mRemote1Encoder.createInputSurface();
                            remoteRenderer.addShareSurface(FvlVideoConsumer.ID_SHARE1, inputSurface);
                            mRemote1Encoder.StartEncoderThread();
                        }
                        /*if (mRemote2Encoder == null) {
                            mRemote2Encoder = new AvcEncoder(1920, 1080, 25, "/sdcard/test2.h264");
                            //remoteRenderer.addOutputSurface(FvlVideoConsumer.ID_SHARE2, mRemote2Encoder.createInputSurface());
                            //mRemote2Encoder.StartEncoderThread();
                            Surface inputSurface = mRemote2Encoder.createInputSurface();
                            //remoteRenderer.addOutputSurface(FvlVideoConsumer.ID_SHARE1, inputSurface);
                            remoteRenderer.addShareSurface(FvlVideoConsumer.ID_SHARE2, inputSurface);
                            mRemote2Encoder.StartEncoderThread();
                        }*/

                        if (mRemote2H264Decoder == null) {
                            //mRemote2H264Decoder = new h264Decoder(remoteRenderer.getSurface(2), "/sdcard/Download/h264_1920_1080_3.h264");
                            //mRemote2H264Decoder.start();
                        }

                        mRemoteH264Decoder = new h264Decoder(remoteRenderer.getSurface(index), "/sdcard/Download/1080p-4.h264");
                        mRemoteH264Decoder.start();
                      /*  if (mRemoteH264Decoder == null) {
                            //mRemoteH264Decoder = new h264Decoder(remoteRenderer.getSurface(1), "/sdcard/Download/h264_1920_1080.h264");
                            mRemoteH264Decoder = new h264Decoder(remoteRenderer.getSurface(0), "/sdcard/Download/1080p-2.h264");
                            mRemoteH264Decoder.start();
                        }*/
                        if (mLocalH264Decoder == null) {
                            //mLocalH264Decoder = new h264Decoder(remoteRenderer.getSurface(0), "/sdcard/Download/h264_1920_1080_2.h264");
                            //mLocalH264Decoder = new h264Decoder(remoteRenderer.getSurface(0), "/sdcard/720p-1.h264");
                            //mLocalH264Decoder.start();
                        }

                        /*if (mRemote1Encoder != null) {
                            //mRemote1Encoder = new AvcEncoder(1920, 1080, 25, "/sdcard/test1.h264");
                            Surface inputSurface = mRemote1Encoder.createInputSurface();
                            //remoteRenderer.addOutputSurface(FvlVideoConsumer.ID_SHARE1, inputSurface);
                            remoteRenderer.addOutputSurface(FvlVideoConsumer.ID_SHARE1, inputSurface);
                            mRemote1Encoder.StartEncoderThread();
                        }

                        if (mRemote2Encoder != null) {
                            //mRemote2Encoder = new AvcEncoder(1920, 1080, 25, "/sdcard/test1.h264");
                            Surface inputSurface = mRemote2Encoder.createInputSurface();
                            //remoteRenderer.addOutputSurface(FvlVideoConsumer.ID_SHARE1, inputSurface);
                            remoteRenderer.addOutputSurface(FvlVideoConsumer.ID_SHARE2, inputSurface);
                            mRemote2Encoder.StartEncoderThread();
                        }*/


                        
            } else {
                sLogger.d("setRemoteDisplay: Remote Display (" + mRemoteDisplay + ") is InActive.");
                mRemoteDisplay.setRenderer(null);
                //nativeSetVideoDisplay(chan, 1, mRemoteDisplay);
                if (mRemote2H264Decoder != null) {
                    mRemote2H264Decoder.interrupt();
                }
                if (mRemoteH264Decoder != null) {
                    mRemoteH264Decoder.interrupt();
                }
                if (mLocalH264Decoder != null) {
                    mLocalH264Decoder.interrupt();
                }
                if (mRemote1Encoder != null) {
                    mRemote1Encoder.StopThread();
                }
                if (mRemote2Encoder != null) {
                    //mRemote2Encoder.StopThread();
                }
                if (remoteRenderer != null) {
                    sLogger.d("setRemoteDisplay: Remote Renderer (" + remoteRenderer + ") stop");
                    remoteRenderer.removeOutputSurface(index);
                } else {
                    sLogger.d("setRemoteDisplay: Remote Renderer (" + remoteRenderer + ") is null.");
                }
                return 0;
            }
        } else {
            sLogger.d("setRemoteDisplay: Remote Display (" + mRemoteDisplay + ") is null.");
        }
        //return nativeSetVideoDisplay(chan, 1, mRemoteDisplay);
        return 0;
    }
}
